////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "BaseEntity.hpp"

#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp>

#include "../Game/DataManager.hpp"
#include "EntityManager.hpp"

#include <SmegTools/Debug/DebugNew.hpp>

namespace smeg {
    namespace core {
        
////////////////////////////////////////////////////////////
/// Default Constructor
////////////////////////////////////////////////////////////
BaseEntity::BaseEntity() :
    BaseObject(),
    m_pTexture( NULL )
{
}
    
////////////////////////////////////////////////////////////
/// Constructor with a texture
////////////////////////////////////////////////////////////
BaseEntity::BaseEntity( const sf::Texture* _pTexture ) :
    BaseObject(),
    m_pTexture( NULL )
{
    SetTexture( _pTexture );
}
    
////////////////////////////////////////////////////////////
/// Constructor with a texture and a rectangle
////////////////////////////////////////////////////////////
BaseEntity::BaseEntity( const sf::Texture* _pTexture, const sf::IntRect& _TextRectangle ) :
    BaseObject(),
    m_pTexture( NULL )
{
    SetTexture( _pTexture );
    SetTextureRect( _TextRectangle );
}
    
////////////////////////////////////////////////////////////
/// Copy Constructor
////////////////////////////////////////////////////////////
BaseEntity::BaseEntity( const BaseEntity& _Copy ) :
    BaseObject( _Copy ),
    m_pTexture( NULL )
{
    SetTexture( _Copy.m_pTexture );
}
    
////////////////////////////////////////////////////////////
/// Destructor
////////////////////////////////////////////////////////////
BaseEntity::~BaseEntity()
{
}


////////////////////////////////////////////////////////////
void BaseEntity::SetTexture(const sf::Texture* _pTexture, bool _bResetRect)
{
    // Recompute the texture area if requested, or if there was no valid texture & rect before
    if (_bResetRect || (!m_pTexture && (m_TextureRect == sf::IntRect()))) {
        SetTextureRect(sf::IntRect(0, 0, _pTexture->getSize().x, _pTexture->getSize().y));
        setOrigin( _pTexture->getSize().x * 0.5f, _pTexture->getSize().y * 0.5f );
    }

    // Assign the new texture
    m_pTexture = _pTexture;
}


////////////////////////////////////////////////////////////
void BaseEntity::SetTextureRect(const sf::IntRect& _TextRectangle)
{
    if (_TextRectangle != m_TextureRect)
    {
        m_TextureRect = _TextRectangle;
        UpdatePositions();
        UpdateTexCoords();
    }
}


////////////////////////////////////////////////////////////
void BaseEntity::SetColor(const sf::Color& _Color)
{
    // Update the vertices' color
    m_Vertices[0].color = _Color;
    m_Vertices[1].color = _Color;
    m_Vertices[2].color = _Color;
    m_Vertices[3].color = _Color;
}


////////////////////////////////////////////////////////////
const sf::Texture* BaseEntity::GetTexture() const
{
    return m_pTexture;
}


////////////////////////////////////////////////////////////
const sf::IntRect& BaseEntity::GetTextureRect() const
{
    return m_TextureRect;
}


////////////////////////////////////////////////////////////
const sf::Color& BaseEntity::GetColor() const
{
    return m_Vertices[0].color;
}


////////////////////////////////////////////////////////////
sf::FloatRect BaseEntity::GetLocalBounds() const
{
    float width = static_cast<float>(std::abs(m_TextureRect.width));
    float height = static_cast<float>(std::abs(m_TextureRect.height));

    return sf::FloatRect(0.f, 0.f, width, height);
}


////////////////////////////////////////////////////////////
sf::FloatRect BaseEntity::GetGlobalBounds() const
{
    return getTransform().transformRect(GetLocalBounds());
}


////////////////////////////////////////////////////////////
void BaseEntity::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
    if (m_pTexture)
    {
        states.transform *= getTransform();
        states.texture = m_pTexture;
        target.draw(m_Vertices, 4, sf::Quads, states);
    }
}


////////////////////////////////////////////////////////////
void BaseEntity::UpdatePositions()
{
    sf::FloatRect bounds = GetLocalBounds();

    m_Vertices[0].position = sf::Vector2f(0, 0);
    m_Vertices[1].position = sf::Vector2f(0, bounds.height);
    m_Vertices[2].position = sf::Vector2f(bounds.width, bounds.height);
    m_Vertices[3].position = sf::Vector2f(bounds.width, 0);
}


////////////////////////////////////////////////////////////
void BaseEntity::UpdateTexCoords()
{
    float left   = static_cast<float>(m_TextureRect.left);
    float right  = left + m_TextureRect.width;
    float top    = static_cast<float>(m_TextureRect.top);
    float bottom = top + m_TextureRect.height;

    m_Vertices[0].texCoords = sf::Vector2f(left, top);
    m_Vertices[1].texCoords = sf::Vector2f(left, bottom);
    m_Vertices[2].texCoords = sf::Vector2f(right, bottom);
    m_Vertices[3].texCoords = sf::Vector2f(right, top);
}

    } // namespace core
} // namespace smeg